// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <pollux/substrait/pollux_substrait_signature.h>
#include <pollux/functions/function_registry.h>

namespace kumo::pollux::substrait {
    std::string PolluxSubstraitSignature::toSubstraitSignature(const TypePtr &type) {
        switch (type->kind()) {
            case TypeKind::BOOLEAN:
                return "bool";
            case TypeKind::TINYINT:
                return "i8";
            case TypeKind::SMALLINT:
                return "i16";
            case TypeKind::INTEGER:
                if (type->isDate()) {
                    return "date";
                }
                return "i32";
            case TypeKind::BIGINT:
                return "i64";
            case TypeKind::REAL:
                return "fp32";
            case TypeKind::DOUBLE:
                return "fp64";
            case TypeKind::VARCHAR:
                return "str";
            case TypeKind::VARBINARY:
                return "vbin";
            case TypeKind::TIMESTAMP:
                return "ts";
            case TypeKind::ARRAY:
                return "list";
            case TypeKind::MAP:
                return "map";
            case TypeKind::ROW:
                return "struct";
            case TypeKind::UNKNOWN:
                return "u!name";
            default:
                POLLUX_UNSUPPORTED(
                    "Substrait type signature conversion not supported for type {}.",
                    mapTypeKindToName(type->kind()));
        }
    }

    // static
    TypePtr PolluxSubstraitSignature::fromSubstraitSignature(
        const std::string &signature) {
        if (signature == "bool") {
            return BOOLEAN();
        }

        if (signature == "i8") {
            return TINYINT();
        }

        if (signature == "i16") {
            return SMALLINT();
        }

        if (signature == "i32") {
            return INTEGER();
        }

        if (signature == "i64") {
            return BIGINT();
        }

        if (signature == "fp32") {
            return REAL();
        }

        if (signature == "fp64") {
            return DOUBLE();
        }

        if (signature == "str") {
            return VARCHAR();
        }

        if (signature == "vbin") {
            return VARBINARY();
        }

        if (signature == "ts") {
            return TIMESTAMP();
        }

        if (signature == "date") {
            return DATE();
        }

        POLLUX_UNSUPPORTED(
            "Substrait type signature conversion to Pollux type not supported for {}.",
            signature);
    }

    std::string PolluxSubstraitSignature::toSubstraitSignature(
        const std::string &functionName,
        const std::vector<TypePtr> &arguments) {
        if (arguments.empty()) {
            return functionName;
        }
        std::vector<std::string> substraitTypeSignatures;
        substraitTypeSignatures.reserve(arguments.size());
        for (const auto &type: arguments) {
            substraitTypeSignatures.emplace_back(toSubstraitSignature(type));
        }
        return functionName + ":" + melon::join("_", substraitTypeSignatures);
    }
} // namespace kumo::pollux::substrait
